;
; interrupt.s -- Contains interrupt service routine wrappers.
;                Based on Bran's kernel development tutorials.
;                Rewritten for JamesM's kernel development tutorials.

; This macro creates a stub for an ISR which does NOT pass it's own
; error code (adds a dummy errcode byte).
%macro ISR_NOERRCODE 1
  global isr%1
  isr%1:
    cli                         ; Disable interrupts firstly.
    push byte 0                 ; Push a dummy error code.
    push byte %1                ; Push the interrupt number.
    jmp isr_common_stub         ; Go to our common handler code.
%endmacro

; This macro creates a stub for an ISR which passes it's own
; error code.
%macro ISR_ERRCODE 1
  global isr%1
  isr%1:
    cli                         ; Disable interrupts.
    push byte %0				; Push the error code.
    push byte %1                ; Push the interrupt number
 	
    jmp isr_common_stub
%endmacro

%macro IRQ 2
	global irq%1
	irq%1:
		cli
		push byte 0
		push byte %2
		jmp irq_common_stub
%endmacro

ISR_NOERRCODE 0			; Division By Zero Exception
ISR_NOERRCODE 1			; Debug Exception
ISR_NOERRCODE 2			; Non Maskable Interrupt
ISR_NOERRCODE 3			; Breakpoint Exception
ISR_NOERRCODE 4			; 'Into Detected Overflow'
ISR_NOERRCODE 5			; Out of Bounds Exception
ISR_NOERRCODE 6			; Invalid Opcode Exception
ISR_NOERRCODE 7			; No Coprocessor Exception
ISR_ERRCODE   8			; Double Fault (Error Code)
ISR_NOERRCODE 9			; Coprocessor segment Overrun
ISR_ERRCODE   10		; Bad TSS (ErrorCode)
ISR_ERRCODE   11		; Segment Not Present (Error Code)
ISR_ERRCODE   12		; Stack Fault (Error Code)
ISR_ERRCODE   13		; General Protection Fault (Error Code)
ISR_ERRCODE   14		; Page Fault (Error Code)
ISR_NOERRCODE 15		; Unknown Interrupt Exception
ISR_NOERRCODE 16		; Coprocessor Fault
ISR_NOERRCODE 17		; Alignment Check Exception
ISR_NOERRCODE 18		; Machine Check Exception
ISR_NOERRCODE 19		; This and all below are reserved.
ISR_NOERRCODE 20		;
ISR_NOERRCODE 21		;
ISR_NOERRCODE 22		;
ISR_NOERRCODE 23		;
ISR_NOERRCODE 24		;
ISR_NOERRCODE 25		;
ISR_NOERRCODE 26		;
ISR_NOERRCODE 27		;
ISR_NOERRCODE 28		;
ISR_NOERRCODE 29		;
ISR_NOERRCODE 30		;
ISR_NOERRCODE 31		;
 
IRQ 0, 32
IRQ 1, 33
IRQ 2, 34
IRQ 3, 35
IRQ 4, 36
IRQ 5, 37
IRQ 6, 38
IRQ 7, 39
IRQ 8, 40
IRQ 9, 41
IRQ 10, 42
IRQ 11, 43
IRQ 12, 44
IRQ 13, 45
IRQ 14, 46
IRQ 15, 47
 
; In isr.c
extern isr_handler
extern irq_handler


;This is our common IRQ stub.
irq_common_stub:
	pusha
	
	mov ax, ds
	push eax
	
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	
	call irq_handler
	
	pop ebx
	
	mov dx, bx
	mov es, bx
	mov fs, bx
	mov gs, bx
	
	popa
	add esp, 8
	sti
	iret


; This is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
    pusha                    ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax

    mov ax, ds               ; Lower 16-bits of eax = ds.
    push eax                 ; save the data segment descriptor

    mov ax, 0x10  ; load the kernel data segment descriptor, the third one in our gdt.
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    call isr_handler

    pop ebx        ; reload the original data segment descriptor
    mov ds, bx
    mov es, bx
    mov fs, bx
    mov gs, bx

    popa                     ; Pops edi,esi,ebp...
    add esp, 8     ; Cleans up the pushed error code and pushed ISR number
    sti			   ; Enable Interrupts
    iret           ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
